import 'dart:io';

import 'package:device_info_plus/device_info_plus.dart';
import 'package:intl/intl.dart';
import 'package:logger/logger.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:path_provider/path_provider.dart';

// 自定义打印
class MyPrinter extends LogPrinter {
  final Map<String, dynamic> deviceInfo;
  final Map<String, dynamic> appInfo;

  MyPrinter({required this.deviceInfo, required this.appInfo});

  @override
  List<String> log(LogEvent event) {
    return [
      '包版本:${appInfo['version']}\n时间:${event.time} - 型号:${deviceInfo['name']} - 版本:${deviceInfo['systemVersion']} \n错误信息:${event.message}'
    ];
  }
}

// 日志文件输出
class ErrorFileOutput extends LogOutput {
  // 控制台输出（用于同时显示所有日志）
  final ConsoleOutput _consoleOutput = ConsoleOutput();
  // 日志文件路径（延迟初始化）
  late final String _logFilePath;
  // 时间格式化器
  final DateFormat _timeFormatter = DateFormat('yyyy-MM-dd HH:mm:ss.SSS');

  ErrorFileOutput() {
    // 初始化日志文件路径
    _initLogFile();
  }

  /// 初始化日志文件（获取应用沙盒路径并创建文件）
  Future<void> _initLogFile() async {
    try {
      // 获取应用文档目录（不同平台路径不同，由path_provider处理）
      final directory = await getApplicationDocumentsDirectory();
      final logDir = Directory('${directory.path}/logs');

      // 确保日志目录存在
      if (!await logDir.exists()) {
        await logDir.create(recursive: true);
      }

      // 日志文件路径（按天分割，避免单文件过大）
      final fileName =
          'error_log_${DateFormat('yyyyMMdd').format(DateTime.now())}.txt';
      _logFilePath = '${logDir.path}/$fileName';
    } catch (e) {
      print('初始化日志文件失败：$e');
    }
  }

  /// 核心方法：处理日志输出
  @override
  void output(OutputEvent event) {
    // 1. 所有日志都输出到控制台（保留实时调试能力）
    _consoleOutput.output(event);

    // 2. 仅Error及以上级别（error/fatal）写入文件
    if (event.level.index >= Level.error.index) {
      _writeErrorToFile(event);
    }
  }

  /// 将Error日志写入文件
  Future<void> _writeErrorToFile(OutputEvent event) async {
    if (_logFilePath.isEmpty) return; // 路径未初始化则返回
    try {
      final file = File(_logFilePath);
      // 构建日志内容（包含时间、级别、消息、错误堆栈）
      final time = _timeFormatter.format(DateTime.now());
      final level = event.level.name.toUpperCase();
      final message = event.lines.join('\n');
      // 注意：OutputEvent没有error和stackTrace属性，错误信息应该包含在lines中
      // 如果需要单独的错误和堆栈跟踪，需要在记录日志时正确传递这些参数

      // 日志格式：时间 [级别] 消息 + 分隔线
      final logContent =
          '[$time] [$level]\n$message\n-------------------------\n';

      // 追加写入文件（若文件不存在则创建）
      await file.writeAsString(logContent, mode: FileMode.append, flush: true);
    } catch (e) {
      log.e('写入错误日志到文件失败：$e');
    }
  }
}

// 自定义日志过滤器
class ReleaseFilter extends LogFilter {
  @override
  bool shouldLog(LogEvent event) {
    return event.level.index >= Level.warning.index;
  }
}

// 日志读取
class LogReader {
  /// 读取指定时间范围内的错误日志
  /// [startTime] 开始时间（包含）
  /// [endTime] 结束时间（包含）
  /// 返回：Map<日期字符串, 日志内容>，键为"yyyy-MM-dd"，值为对应文件的日志文本
  static Future<Map<String, String>> readLogsInRange({
    required DateTime startTime,
    required DateTime endTime,
  }) async {
    final result = <String, String>{};

    try {
      // 1. 获取日志目录
      final appDocDir = await getApplicationDocumentsDirectory();
      final logDir = Directory('${appDocDir.path}/logs');

      // 检查日志目录是否存在
      if (!await logDir.exists()) {
        print('日志目录不存在');
        return result;
      }

      // 2. 获取目录下所有日志文件
      final logFiles = await logDir.list().toList();
      // 3. 遍历文件，筛选出时间范围内的文件
      for (final fileEntity in logFiles) {
        if (fileEntity is File) {
          // 解析文件名中的日期（格式：error_log_20251016.txt）
          final fileName = fileEntity.path.split('/').last;
          final dateStr = _extractDateFromFileName(fileName);
          if (dateStr == null) continue;

          // 截断时间部分，只保留年月日（确保和传入的时间范围比较时只看日期）
          final normalizedFileDate = DateTime(
              int.parse(dateStr.substring(0, 4)),
              int.parse(dateStr.substring(4, 6)),
              int.parse(dateStr.substring(6, 8)));
          final normalizedStartTime =
              DateTime(startTime.year, startTime.month, startTime.day);
          final normalizedEndTime =
              DateTime(endTime.year, endTime.month, endTime.day);

          // 判断文件日期是否在范围内
          if (normalizedFileDate.isAfter(normalizedEndTime) ||
              normalizedFileDate.isBefore(normalizedStartTime)) {
            continue;
          }

          // 4. 读取符合条件的文件内容
          final content = await fileEntity.readAsString();
          // 键格式化为"yyyy-MM-dd"，便于阅读
          final displayDate =
              DateFormat('yyyy-MM-dd').format(normalizedStartTime);
          result[displayDate] = content;
        }
      }

      // 5. 按日期排序（升序）
      final sortedEntries = result.entries.toList()
        ..sort((a, b) => a.key.compareTo(b.key));
      return Map.fromEntries(sortedEntries);
    } catch (e) {
      print('读取日志失败：$e');
      return result;
    }
  }

  /// 从文件名中提取日期字符串（如从"error_log_20251016.txt"提取"20251016"）
  static String? _extractDateFromFileName(String fileName) {
    // 正则匹配文件名格式：error_log_数字.txt
    final regex = RegExp(r'error_log_(\d{8})\.txt');
    final match = regex.firstMatch(fileName);
    return match?.group(1); // 返回捕获的日期部分（如"20251016"）
  }
}

// 自定义日志
class CustomLogger {
  static CustomLogger? _instance;
  static Logger? _logger;

  factory CustomLogger() {
    _instance ??= CustomLogger._();
    return _instance!;
  }

  CustomLogger._() {
    init();
  }

  void init() async {
    const flutterEnv = String.fromEnvironment('FLUTTER_ENV');
    final deviceInfo = await _getDeviceInfo();
    final appInfo = await _getAppInfo();

    final printer = MyPrinter(deviceInfo: deviceInfo, appInfo: appInfo);

    _logger = Logger(
        filter: flutterEnv == 'production' ? ReleaseFilter() : null,
        printer: printer,
        output: flutterEnv == 'production' ? ErrorFileOutput() : null);
  }

  /// info 级别日志
  void i(String message, {dynamic error, StackTrace? stackTrace}) {
    _logger?.i(message, error: error, stackTrace: stackTrace);
  }

  /// warning 级别日志
  void w(String message, {dynamic error, StackTrace? stackTrace}) {
    _logger?.w(message, error: error, stackTrace: stackTrace);
  }

  /// error 级别日志
  void e(String message, {dynamic error, StackTrace? stackTrace}) {
    _logger?.e(message, error: error, stackTrace: stackTrace);
  }

  /// fatal 级别日志
  void f(String message, {dynamic error, StackTrace? stackTrace}) {
    _logger?.f(message, error: error, stackTrace: stackTrace);
  }

  // 日志读取方法
  Future<dynamic> readLogsInRange({
    required DateTime startTime,
    required DateTime endTime,
  }) async {
    final logs =
        await LogReader.readLogsInRange(startTime: startTime, endTime: endTime);
    if (logs.isEmpty) {
      return {};
    }
    return logs;
  }

  // 获取设备信息（依赖 device_info_plus）
  Future<Map<String, dynamic>> _getDeviceInfo() async {
    final deviceInfoPlugin = DeviceInfoPlugin();
    final dynamic data = {
      'model': 'unknown',
      'name': 'unknown',
      'systemVersion': 'unknown'
    };
    if (Platform.isAndroid) {
      final info = await deviceInfoPlugin.androidInfo;
      data['model'] = info.model;
      data['name'] = info.name;
      data['systemVersion'] = info.version.release;
      return data;
    } else if (Platform.isIOS) {
      final info = await deviceInfoPlugin.iosInfo;
      data['model'] = info.model;
      data['name'] = info.name;
      data['systemVersion'] = info.systemVersion;
      return data;
    }
    return data;
  }

  // 获取应用信息（依赖 package_info_plus）
  Future<Map<String, dynamic>> _getAppInfo() async {
    final packageInfo = await PackageInfo.fromPlatform();
    return {'version': packageInfo.version};
  }
}

final log = CustomLogger();
